<?php

namespace core;

use BadMethodCallException;

/**
 * 一个简单的、基于 Session 的 ORM 基类
 */
abstract class Model
{
    /** @var string 表名，将在子类中被覆盖 */
    protected string $table = '';

    /** @var string 主键 */
    protected string $primaryKey = 'id';

    /** @var array 模型的属性 */
    protected array $attributes = [];

    /** @var bool 标记模型实例是否已存在于“数据库”中 */
    protected bool $exists = false;

    public function __construct(array $attributes = [])
    {
        $this->fill($attributes);
    }

    /**
     * 填充模型的属性
     */
    public function fill(array $attributes): self
    {
        foreach ($attributes as $key => $value) {
            $this->setAttribute($key, $value);
        }
        return $this;
    }

    /**
     * 静态方法：获取所有记录
     */
    public static function all(): array
    {
        $instance = new static();
        $items = $_SESSION[$instance->table] ?? [];
        return array_map(fn($item) => (new static($item))->syncOriginal(), $items);
    }

    /**
     * 静态方法：通过主键查找记录
     */
    public static function find(int $id): ?static
    {
        $instance = new static();
        $item = $_SESSION[$instance->table][$id] ?? null;
        if ($item) {
            return (new static($item))->syncOriginal();
        }
        return null;
    }

    /**
     * 静态方法：根据条件查找第一条记录
     */
    public static function firstWhere(string $column, $value): ?static
    {
        $instance = new static();
        foreach ($_SESSION[$instance->table] ?? [] as $item) {
            if (isset($item[$column]) && $item[$column] === $value) {
                return (new static($item))->syncOriginal();
            }
        }
        return null;
    }

    /**
     * 静态方法：创建并保存新记录
     */
    public static function create(array $attributes): static
    {
        $instance = new static($attributes);
        $instance->save();
        return $instance;
    }

    /**
     * 保存模型（插入或更新）
     */
    public function save(): bool
    {
        if ($this->exists) {
            return $this->performUpdate();
        }
        return $this->performInsert();
    }

    /**
     * 删除模型
     */
    public function delete(): bool
    {
        if (!$this->exists) {
            return false;
        }
        $id = $this->getAttribute($this->primaryKey);
        unset($_SESSION[$this->table][$id]);
        $this->exists = false;
        return true;
    }

    protected function performInsert(): bool
    {
        $nextIdKey = 'next_' . rtrim($this->table, 's') . '_id';
        $id = $_SESSION[$nextIdKey]++;

        $this->setAttribute($this->primaryKey, $id);
        $_SESSION[$this->table][$id] = $this->attributes;

        $this->exists = true;
        return true;
    }

    protected function performUpdate(): bool
    {
        $id = $this->getAttribute($this->primaryKey);
        $_SESSION[$this->table][$id] = $this->attributes;
        return true;
    }

    /**
     * 将当前状态标记为“已存在”
     */
    public function syncOriginal(): self
    {
        $this->exists = true;
        return $this;
    }

    /**
     * 魔术方法，用于获取属性
     */
    public function __get(string $key)
    {
        return $this->getAttribute($key);
    }

    /**
     * 魔术方法，用于设置属性
     */
    public function __set(string $key, $value): void
    {
        $this->setAttribute($key, $value);
    }

    public function getAttribute(string $key)
    {
        $method = 'get' . str_replace('_', '', ucwords($key, '_')) . 'Attribute';
        if (method_exists($this, $method)) {
            return $this->{$method}();
        }
        return $this->attributes[$key] ?? null;
    }

    public function setAttribute(string $key, $value): void
    {
        $method = 'set' . str_replace('_', '', ucwords($key, '_')) . 'Attribute';
        if (method_exists($this, $method)) {
            $this->{$method}($value);
        } else {
            $this->attributes[$key] = $value;
        }
    }

    public function __isset(string $key): bool
    {
        return isset($this->attributes[$key]);
    }
}
